package com.mc.fastkit.widget

import android.app.Activity
import android.content.Context
import android.content.Intent
import android.os.Parcelable
import androidx.activity.ComponentActivity
import androidx.activity.result.ActivityResult
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContract
import androidx.annotation.MainThread
import androidx.core.app.ActivityOptionsCompat
import androidx.fragment.app.Fragment
import kotlinx.parcelize.Parcelize

/**
 * [ActivityResultLauncher]的辅助类，帮助其更简单的调用和获得回调；
 * 和[ActivityResultLauncher]一样，需要先在[Activity.onCreate]中注册，然后在需要的地方调用[launch]；
 * 此组件有缺陷，在需要考虑页面重建时，不要使用
 * @author: MasterChan
 * @date: 2022-06-26 17:12
 */
class ActivityResultHelper {

    private lateinit var activity: Activity
    private lateinit var activityResultLauncher: ActivityResultLauncher<Intent>
    private val activityResultMap = mutableMapOf<String, (ActivityResult) -> Unit>()
    private val callbackFlag = "callbackFlag"

    @MainThread
    fun register(activity: ComponentActivity) {
        this.activity = activity
        activityResultLauncher = activity.registerForActivityResult(ActivityForContract()) {
            handleCallback(it)
        }
    }

    @MainThread
    fun register(fragment: Fragment) {
        this.activity = fragment.requireActivity()
        activityResultLauncher = fragment.registerForActivityResult(ActivityForContract()) {
            handleCallback(it)
        }
    }

    fun launch(clazz: Class<out Activity>, callback: (ActivityResult) -> Unit) {
        launch(Intent(activity, clazz), null, callback)
    }

    fun launch(
        intent: Intent,
        options: ActivityOptionsCompat? = null,
        callback: (ActivityResult) -> Unit
    ) {
        val key = System.nanoTime().toString()
        intent.putExtra(callbackFlag, key)
        activityResultMap[key] = callback
        activityResultLauncher.launch(intent, options)
    }

    private fun handleCallback(callback: ActivityResultCallback) {
        val key = callback.input?.getStringExtra(callbackFlag)
        activityResultMap[key]?.invoke(ActivityResult(callback.resultCode, callback.output))
        activityResultMap.remove(key)
    }

    @MainThread
    fun unregister() {
        activityResultLauncher.unregister()
    }

    open class ActivityForContract : ActivityResultContract<Intent, ActivityResultCallback>() {
        private var input: Intent? = null

        override fun createIntent(context: Context, input: Intent): Intent {
            this.input = input
            return input
        }

        override fun parseResult(resultCode: Int, intent: Intent?): ActivityResultCallback {
            return ActivityResultCallback(resultCode, input, intent)
        }
    }

    @Parcelize
    open class ActivityResultCallback(
        val resultCode: Int, val input: Intent?, val output: Intent?
    ) : Parcelable
}